@node Interacting with the Scheme heap in C
@section Interacting with the Scheme heap in C

@cindex GC protection in C
Scheme48 uses a precise copying garbage collector.  Any code that
allocates objects within the Scheme48 heap may trigger a garbage
collection.  Variables bound to values in the Scheme48 heap need to be
registered with the garbage collector so that the value will be safely
held and so that the variables will be updated if the garbage collector
moves the object.  The garbage collector has no facility for updating
pointers to the interiors of objects, so such pointers, for example the
ones returned by @code{S48_EXTRACT_STRING}, will likely become invalid
when a garbage collection occurs.

@deftypefn {C macro} {} S48_DECLARE_GC_PROTECT (@var{n})
@deftypefnx {C macro} void S48_GC_PROTECT_@var{n} (s48_value @var{var}@sub{1}, @dots{}, s48_value @var{var}@sub{@var{n}})
@deftypefnx {C macro} void S48_GC_UNPROTECT ()
@code{S48_DECLARE_GC_PROTECT}, where 1 <= @var{n} <= 9, allocates
storage for registering @var{n} variables.  At most one use of
@code{S48_DECLARE_GC_PROTECT} may occur in a block.  After declaring a
GC protection, @code{S48_GC_PROTECT_@var{n}} registers the @var{n}
variables with the garbage collector.  It must be within the scope that
the @code{S48_DECLARE_GC_PROTECT} occurred in and before any code that
can cause a garbage collection.  @code{S48_GC_UNPROTECT} removes the
current block's protected variables from the garbage collector's list.
It must be called at the end of the block after any code that may cause
a garbage collection.  Omitting any of the three may cause serious and
hard-to-debug problems, because the garbage collector may relocate an
object and invalidate unprotected @code{s48_value} pointers.  If not
@code{S48_DECLARE_GC_PROTECT} is matched with a @code{S48_GC_UNPROTECT}
or vice versa, a @code{gc-protection-mismatch} exception is raised when
a C procedure returns to Scheme.
@end deftypefn

@deftypefn {C macro} {void *} S48_GC_PROTECT_GLOBAL (@var{global})
@deftypefnx {C macro} void S48_GC_UNPROTECT_GLOBAL (void *@var{handle})
@code{S48_GC_PROTECT_GLOBAL} permanently registers the l-value
@var{global} with the system as a garbage collection root.  It returns
a pointer which may then be supplied to @code{S48_GC_UNPROTECT_GLOBAL}
to unregister the l-value as a root.
@end deftypefn

@subsection Keeping C data structures in the Scheme heap

@cindex storing C data in the Scheme heap
C data structures can be stored within the Scheme heap by embedding
them inside @embedref{Bitwise manipulation, byte vectors}.  The
following macros can be used to create and access embedded C objects.

@deftypefn {C macro} s48_value S48_MAKE_VALUE (@var{type})
@deftypefnx {C macro} @var{type} S48_EXTRACT_VALUE (s48_value @var{bytev}, @var{type})
@deftypefnx {C macro} {@var{type} *} S48_EXTRACT_VALUE_POINTER (s48_value @var{bytev}, @var{type})
@deftypefnx {C macro} void S48_SET_VALUE (s48_value @var{bytev}, @var{type}, @var{type} @var{value})
@code{S48_MAKE_VALUE} allocates a byte vector large enough to hold a C
value whose type is @var{type}.  @code{S48_EXTRACT_VALUE} returns the
contents of the byte vector @var{bytev} cast to @var{type}, and
@code{S48_EXTRACT_VALUE_POINTER} returns a pointer to the contents of
the byte vector, which is valid only until the next garbage collection.
@code{S48_SET_VALUE} stores a value into the byte vector.
@end deftypefn

@subsection C code and heap images

@cindex restoring C data after resuming images
@cindex dumping Scheme heap images with C data
@cindex record resumers
Scheme48 uses dumped heap images to restore a previous system state.
The Scheme48 heap is written into a file in a machine-independent and
operating-system-independent format.  The procedures described above,
however, may be used to create objects in the Scheme heap that contain
information specific to the current machine, operating system, or
process.  A heap image containing such objects may not work correctly
when resumed.

To address this problem, a record type may be given a @dfn{resumer}
procedure.  On startup, the resumer procedure for a record type is
applied to each record of that type in the image being restarted.  This
procedure can update the record in a manner appropriate to the machine,
operating system, or process used to resume the image.  Note, though,
that there is no reliable order in which record resumer procedures are
applied.  To specify the resumer for a record type, use the
@code{define-record-resumer} procedure from the @embedref{Records,
@code{record-types} structure}.
